package baseFx.tests.database;

import baseFx.database.DbTable;
import baseFx.database.ResetSpace;
import baseFx.database.SqlParam;
import baseFx.database.execute.DbExecute;
import baseFx.database.execute.SqlInsertContext;
import baseFx.database.execute.SqlUpdateContext;
import baseFx.database.execute.impl.MysqlExecute;
import baseFx.database.where.ExecuteWhere;
import org.junit.Assert;
import org.junit.Test;

import javax.annotation.Resource;
import java.util.Date;

public class MysqlExecuteTests {
    @Test
    public void 测试Insert() {
        SqlParam param = new SqlParam();
        DbExecute execute = new MysqlExecute(new MockJDBCSql()) {
            @Override
            protected SqlParam createInsert(SqlInsertContext data) {
                SqlParam sp = super.createInsert(data);
                param.command = sp.command;
                param.args.putAll(sp.args);
                return sp;
            }
        };
        Model model = new Model();
        model.id = 1;
        model.name = "abc";
        model.time = new Date();
        execute.insert(model);

        Assert.assertEquals("insert into `Model`(`id`,`name`,`time`) values(#id,#name,#time)", param.command);
        Assert.assertEquals(param.args.get("id"), model.id);
        Assert.assertEquals(param.args.get("name"), model.name);
        Assert.assertEquals(param.args.get("time"), model.time);
    }

    @Test
    public void 测试Delete() {
        SqlParam param = new SqlParam();
        DbExecute execute = new MysqlExecute(new MockJDBCSql()) {
            @Override
            protected SqlParam createDelete(ExecuteWhere where, Integer timeout) {
                SqlParam sp = super.createDelete(where, timeout);
                param.command = sp.command;
                param.args.putAll(sp.args);
                return sp;
            }
        };
        Model model = new Model();
        model.id = 1;
        model.name = "abc";
        model.time = new Date();
        execute.delete(model);

        Assert.assertEquals("delete from `Model` where `id`=#eq_id and `name`=#eq_name and `time`=#eq_time", param.command);
        Assert.assertEquals(param.args.get("eq_id"), model.id);
        Assert.assertEquals(param.args.get("eq_name"), model.name);
        Assert.assertEquals(param.args.get("eq_time"), model.time);
    }


    @Test
    public void 测试Update() {
        SqlParam param = new SqlParam();
        DbExecute execute = new MysqlExecute(new MockJDBCSql()) {
            @Override
            protected SqlParam createUpdate(SqlUpdateContext context) {
                SqlParam sp = super.createUpdate(context);
                param.command = sp.command;
                param.args.putAll(sp.args);
                return sp;
            }
        };
        Model model = new Model();
        model.id = 1;
        model.name = "abc";
        model.time = new Date();
        execute.update(model);

        Assert.assertEquals("update `Model` set `name`=#set_name,`time`=#set_time where `id`=#eq_id", param.command);
        Assert.assertEquals(param.args.get("eq_id"), model.id);
        Assert.assertEquals(param.args.get("set_name"), model.name);
        Assert.assertEquals(param.args.get("set_time"), model.time);
    }


    @Test
    public void 测试Proc() {
        SqlParam param = new SqlParam();
        DbExecute execute = new MysqlExecute(new MockJDBCSql()) {
            @Override
            protected SqlParam createProc(Object model, Integer timeout) {
                SqlParam sp = super.createProc(model, timeout);
                param.command = sp.command;
                param.args.putAll(sp.args);
                return sp;
            }
        };
        Model model = new Model();
        model.id = 1;
        model.name = "abc";
        model.time = new Date();
        execute.proc(model);

        Assert.assertEquals("Model", param.command);
        Assert.assertEquals(param.args.get("id"), model.id);
        Assert.assertEquals(param.args.get("name"), model.name);
        Assert.assertEquals(param.args.get("time"), model.time);
    }

    @Test
    public void 重置表名() {
        SqlParam param = new SqlParam();
        DbExecute execute = new MysqlExecute(new MockJDBCSql()) {
            @Override
            protected SqlParam createInsert(SqlInsertContext data) {
                SqlParam sp = super.createInsert(data);
                param.command = sp.command;
                param.args.putAll(sp.args);
                return sp;
            }
        };
        Model2 model = new Model2();
        model.id = 1;
        try (ResetSpace rs = execute.resetTable(Model2.class, "2019")) {
            execute.insert(model);
        }
        Assert.assertEquals("insert into `model_2019`(`id`) values(#id)", param.command);
        Assert.assertEquals(param.args.get("id"), model.id);
    }

    @DbTable(allowDelete = true)
    private static class Model {
        public Integer id;
        public String name;
        public Date time;
    }

    @Resource(name = "model_{0}")
    private static class Model2 {
        public Integer id;
    }
}
